﻿using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
using System.Reflection;
using System.IO;
using MineMES.Application.AppHelper.TypeOfDI;
using IDapperServices;
using IDapperRepository;
using DapperRepository;
using DapperServices;

namespace MineMES.Application.AppHelper
{
    //自定义扩展
    public static class ServiceCollectionExtension
    {
        /// <summary>
        /// 自动依赖注入
        /// </summary>
        /// <param name="services"></param>
        public static IServiceCollection AddAutoDIService(this IServiceCollection services)
        {
            //var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
            string path = AppContext.BaseDirectory;
            var referencedAssemblies = Directory.GetFiles(path, "*.Application.dll").Select(Assembly.LoadFrom).ToArray();
            Set(typeof(IScoped), path, referencedAssemblies, services);
            //Set(typeof(ITransient), path, referencedAssemblies, services);
            //Set(typeof(ISingleton), path, referencedAssemblies, services);
            services.AddTransient(typeof(IDapperBaseServices<>), typeof(DapperBaseServices<>));
            services.AddTransient(typeof(IDapperBaseRepository<>), typeof(DapperBaseRepository<>));
            return services;
        }

        private static void Set(Type iType, string path, Assembly[] referencedAssemblies, IServiceCollection services)
        {
            var types = referencedAssemblies
                .SelectMany(a => a.DefinedTypes)
                .Select(type => type.AsType());
            var implementTypes = types.Where(x => x.IsClass).ToArray();
            var interfaceTypes = types.Where(x => x.IsInterface).ToArray();
            foreach (var implementType in implementTypes)
            {
                var interfaceType = interfaceTypes.FirstOrDefault(x => x.IsAssignableFrom(implementType));
                var fullName = "MineMES.Application." + implementType.Name;
                if (implementType.FullName != fullName)
                    continue;
                if (interfaceType != null)
                {
                    if (iType.Name == nameof(IScoped))
                    {
                        services.AddScoped(interfaceType, implementType);
                    }
                    else if (iType.Name == nameof(ITransient))
                    {
                        services.AddTransient(interfaceType, implementType);
                    }
                    else if (iType.Name == nameof(ISingleton))
                    {
                        services.AddSingleton(interfaceType, implementType);
                    }
                }
                else
                {
                    if (iType.Name == nameof(IScoped))
                    {
                        services.AddScoped(implementType);
                    }
                    else if (iType.Name == nameof(ITransient))
                    {
                        services.AddTransient(implementType);
                    }
                    else if (iType.Name == nameof(ISingleton))
                    {
                        services.AddSingleton(implementType);
                    }
                }
            }
        }
    }
}
